"""
Created on 23-Jul-2009

@author: dexen
"""


import rpyc
from rpyc.utils import server

import dexen
from dexen.system.common import service
from dexen.system.node.master import comm
from dexen.system.common.meta import JobMeta
from dexen.system.common.base import MyManager
from dexen.system.common.service import DexenAddr
from dexen.system.node.master.core import MasterCore


MyManager.register("MasterComm", comm.MasterComm)


#===============================================================================
# Globals
#===============================================================================
        
def start(_master_name, _node_name, _reg_addr, is_local=False, is_quiet=True):
    global manager, node_name, master_name, reg_addr, svr

    manager = MyManager()
    manager.daemon = True
    manager.start()    
    node_name = _node_name
    master_name = _master_name
    reg_addr = _reg_addr
    assert isinstance(reg_addr, DexenAddr)
    _logger = service.get_rpyc_logger(master_name.upper(), is_quiet)
    MasterService.ALIASES = [master_name]
    svr = server.ThreadedServer(MasterService, 
                                protocol_config=service.default_config,
                                auto_register=False,
                                logger=_logger)
    conn = reg_addr.get_conn()
    my_addr = DexenAddr(service.get_my_ip(is_local), svr.port)
    conn.root.register_master(master_name, my_addr)
    conn.close()
    print "%s has started."%(master_name,)
    svr.start()
    manager.shutdown()
    #print "Current process id is", os.getpid()
    print "%s is terminated."%(master_name,)


#===============================================================================
# Service
#===============================================================================
class MasterService(dexen.Service):
    def on_connect(self):
        pass
    
    def on_disconnect(self):
        pass
        
    def schedule(self, slave_names):
        self.comm.assign_slaves(slave_names)

    def run_job(self, job_meta):
        job_meta = rpyc.classic.obtain(job_meta)
        assert isinstance(job_meta, JobMeta)
        self.comm = manager.MasterComm(master_name)
        self.core = MasterCore(job_meta, self.comm, reg_addr)
        self.core.start()

    def stop_job(self):
        self.core.terminate()
        self.core.join()
        svr.close()

    def get_updates(self):
        return self.comm.get_actions()
    
    def can_schedule(self):
        return self.comm.can_schedule()

    def num_slaves_can_schedule(self):
        return self.comm.num_slaves_needed()
